﻿using System.Collections.Concurrent;
using System.Net.WebSockets;
using System.Net;
using System.Text;
using BaseUtils.Logger;
using System.Threading.Tasks;
using System;
using System.Threading;
using System.Collections.Generic;

namespace NW_WEB_Service.com.utils
{
    public class WebSocketServer
    {
        private readonly ConcurrentDictionary<string, WebSocket> WebSocketClients = new ConcurrentDictionary<string, WebSocket>();
        // 新增：为每个客户端维护一个发送锁，确保SendAsync不会并发执行
        private readonly ConcurrentDictionary<string, SemaphoreSlim> _clientSendLocks = new ConcurrentDictionary<string, SemaphoreSlim>();
        private HttpListener _listener;
        private readonly List<string> _urls;
        private bool _isRunning;

        // 事件定义（保持不变）
        public event Action<string, string> OnMessageReceived;
        public event Action<string> OnClientConnected;
        public event Action<string> OnClientDisconnected;
        public event Action<Exception> OnErrorOccurred;

        public WebSocketServer(List<string> urls)
        {
            _urls = urls ?? throw new ArgumentNullException(nameof(urls), "监听URL列表不能为null");
            if (_urls.Count == 0)
            {
                throw new ArgumentException("至少需要提供一个监听URL", nameof(urls));
            }
        }

        public void Open()
        {
            // 原有逻辑保持不变
            if (_isRunning)
            {
                Console.WriteLine("服务器已在运行中");
                return;
            }

            _isRunning = true;
            _listener = new HttpListener();

            foreach (string url in _urls)
            {
                _listener.Prefixes.Add(url);
                Console.WriteLine($"已添加监听地址: {url}");
            }

            try
            {
                _listener.Start();
                Console.WriteLine($"WebSocket服务器已启动，共监听 {_urls.Count} 个地址");
                _ = AcceptClientsAsync();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"启动服务器失败: {ex.Message}");
                OnErrorOccurred?.Invoke(ex);
                _isRunning = false;
            }
        }

        public async Task Stop()
        {
            if (!_isRunning) return;

            _isRunning = false;
            _listener?.Stop();

            // 关闭所有客户端连接并释放锁
            foreach (var client in WebSocketClients)
            {
                if (client.Value.State == WebSocketState.Open)
                {
                    await client.Value.CloseAsync(WebSocketCloseStatus.NormalClosure, "服务器关闭", CancellationToken.None);
                }
                // 释放对应的发送锁
                _clientSendLocks.TryRemove(client.Key, out var lockObj);
                lockObj?.Dispose();
            }

            WebSocketClients.Clear();
            _clientSendLocks.Clear();
            Console.WriteLine("WebSocket服务器已停止");
        }

        /// <summary>
        /// 向所有连接的客户端广播消息（添加同步锁）
        /// </summary>
        public async Task BroadcastMessage(string message)
        {
            if (WebSocketClients.Count <= 0 || string.IsNullOrEmpty(message))
            {
                return;
            }

            var buffer = Encoding.UTF8.GetBytes(message);

            foreach (var client in WebSocketClients)
            {
                var clientId = client.Key;
                var webSocket = client.Value;

                if (webSocket.State != WebSocketState.Open)
                {
                    continue;
                }

                // 获取该客户端的发送锁，确保并发安全
                var sendLock = _clientSendLocks.GetOrAdd(clientId, _ => new SemaphoreSlim(1, 1));
                try
                {
                    // 等待锁（最多等待5秒，避免死锁）
                    if (await sendLock.WaitAsync(5000, CancellationToken.None))
                    {
                        await webSocket.SendAsync(
                            new ArraySegment<byte>(buffer, 0, buffer.Length),
                            WebSocketMessageType.Text,
                            true,
                            CancellationToken.None);
                    }
                    else
                    {
                        LoggerService.Warning($"向客户端 {clientId} 发送消息超时（锁等待超时）");
                    }
                }
                catch (Exception ex)
                {
                    LoggerService.Error($"向客户端 {clientId}，发送的数据：{message}， 发送消息失败，原因: {ex.Message}", ex);
                    OnErrorOccurred?.Invoke(ex);
                }
                finally
                {
                    // 确保锁释放
                    if (sendLock.CurrentCount == 0)
                    {
                        sendLock.Release();
                    }
                }
            }
        }

        /// <summary>
        /// 向指定客户端发送消息（添加同步锁）
        /// </summary>
        public async Task SendToClient(string clientId, string message)
        {
            if (string.IsNullOrEmpty(clientId) || string.IsNullOrEmpty(message) || !WebSocketClients.TryGetValue(clientId, out var webSocket))
            {
                return;
            }

            if (webSocket.State != WebSocketState.Open)
            {
                return;
            }

            var buffer = Encoding.UTF8.GetBytes(message);
            // 获取该客户端的发送锁
            var sendLock = _clientSendLocks.GetOrAdd(clientId, _ => new SemaphoreSlim(1, 1));

            try
            {
                // 等待锁（最多等待5秒）
                if (await sendLock.WaitAsync(5000, CancellationToken.None))
                {
                    await webSocket.SendAsync(
                        new ArraySegment<byte>(buffer, 0, buffer.Length),
                        WebSocketMessageType.Text,
                        true,
                        CancellationToken.None);
                }
                else
                {
                    LoggerService.Warning($"向客户端 {clientId} 发送消息超时（锁等待超时）");
                }
            }
            catch (Exception ex)
            {
                LoggerService.Error($"向客户端 {clientId} 发送消息失败: {ex.Message}", ex);
                OnErrorOccurred?.Invoke(ex);
            }
            finally
            {
                // 确保锁释放
                if (sendLock.CurrentCount == 0)
                {
                    sendLock.Release();
                }
            }
        }

        private async Task AcceptClientsAsync()
        {
            while (_isRunning)
            {
                try
                {
                    var context = await _listener.GetContextAsync();

                    if (!context.Request.IsWebSocketRequest)
                    {
                        context.Response.StatusCode = 400;
                        context.Response.Close();
                        continue;
                    }

                    var webSocketContext = await context.AcceptWebSocketAsync(null);
                    var webSocket = webSocketContext.WebSocket;
                    var clientId = Guid.NewGuid().ToString();

                    // 客户端连接时，初始化其发送锁
                    _clientSendLocks.TryAdd(clientId, new SemaphoreSlim(1, 1));
                    WebSocketClients.TryAdd(clientId, webSocket);

                    Console.WriteLine($"新客户端连接，ID: {clientId}，来自: {context.Request.RemoteEndPoint}，当前连接数: {WebSocketClients.Count}");
                    OnClientConnected?.Invoke(clientId);

                    _ = HandleClientAsync(clientId, webSocket, context.Response);
                }
                catch (Exception ex)
                {
                    if (_isRunning)
                    {
                        Console.WriteLine($"接受客户端连接时发生错误: {ex.Message}");
                        OnErrorOccurred?.Invoke(ex);
                    }
                }
            }
        }

        private async Task HandleClientAsync(string clientId, WebSocket webSocket, HttpListenerResponse response)
        {
            var buffer = new byte[1024 * 4];

            try
            {
                while (webSocket.State == WebSocketState.Open && _isRunning)
                {
                    var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);

                    if (result.MessageType == WebSocketMessageType.Text)
                    {
                        var message = Encoding.UTF8.GetString(buffer, 0, result.Count);
                        Console.WriteLine($"收到客户端 {clientId} 的消息: {message}");
                        OnMessageReceived?.Invoke(clientId, message);
                    }
                    else if (result.MessageType == WebSocketMessageType.Close)
                    {
                        await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "正常关闭", CancellationToken.None);
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"处理客户端 {clientId} 时发生错误: {ex.Message}");
                OnErrorOccurred?.Invoke(ex);
            }
            finally
            {
                // 客户端断开连接时，清理WebSocket和对应的发送锁
                WebSocketClients.TryRemove(clientId, out _);
                webSocket.Dispose();
                response.Close();

                // 释放发送锁资源
                if (_clientSendLocks.TryRemove(clientId, out var sendLock))
                {
                    sendLock.Dispose();
                }

                Console.WriteLine($"客户端 {clientId} 已断开连接，当前连接数: {WebSocketClients.Count}");
                OnClientDisconnected?.Invoke(clientId);
            }
        }
    }
}